package com.sd.web.im;
import com.sd.common.annotations.ForbidRepeatSubmit;
import com.sd.common.beans.AccessToken;
import com.sd.common.beans.ApiResponse;
import com.sd.common.beans.AppInfo;
import com.sd.common.beans.TokenInfo;
import com.sd.common.constant.CommonConstants;
import com.sd.common.utils.MD5Util;
import com.sd.service.AppInfoService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Calendar;
import java.util.Date;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
/**
 * token
 * @author yexinming
 */
@RestController
@RequestMapping("/api/token")
public class TokenController {
    private static final Logger log = LoggerFactory.getLogger(TokenController.class);
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private AppInfoService appInfoService;
    /**
     * API Token
     * @param sign
     * @return
     */
    @ForbidRepeatSubmit(5000)
    @PostMapping("/api_token")
    public ApiResponse<AccessToken> apiToken(String appId, @RequestHeader("timestamp") String timestamp, @RequestHeader("sign") String sign) {
        try {
            Assert.isTrue(!StringUtils.isEmpty(appId) && !StringUtils.isEmpty(timestamp) && !StringUtils.isEmpty(sign), "参数错误");

            long reqeustInterval = System.currentTimeMillis() - Long.valueOf(timestamp);
            Assert.isTrue(reqeustInterval < 5 * 60 * 1000, CommonConstants.ApiCodeEnum.TOKEN_EXPIRE.getCode());

            // 1. 根据appId查询数据库获取appSecret
            AppInfo appInfo = appInfoService.getByAppId(appId);
            Assert.isTrue(appInfo!=null,CommonConstants.ApiCodeEnum.SIGN_ERROR.getCode());

            // 2. 校验签名
            String signString = timestamp + appId + appInfo.getAppSecret();
            String signature = MD5Util.encode(signString);
            log.info(signature);
            Assert.isTrue(signature.equals(sign), CommonConstants.ApiCodeEnum.SIGN_ERROR.getCode());

            // 3. 如果正确生成一个token保存到redis中，如果错误返回错误信息
            AccessToken accessToken = this.saveToken(0, appInfo);
            return ApiResponse.success(accessToken);
        }catch (Exception e){
            log.error("error",e);
            String code = e.getMessage();
            if(CommonConstants.ApiCodeEnum.contains(code)){
                return ApiResponse.error(code,CommonConstants.ApiCodeEnum.getMsg(code));
            }
            return ApiResponse.error(CommonConstants.ApiCodeEnum.UNKNOW_ERROR.getCode(), CommonConstants.ApiCodeEnum.UNKNOW_ERROR.getMsg());
        }
    }

    private AccessToken saveToken(int tokenType, AppInfo appInfo) {
        String token = UUID.randomUUID().toString();
        // token有效期为2小时
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.SECOND, 7200);
        Date expireTime = calendar.getTime();

        // 4. 保存token
        ValueOperations<String, TokenInfo> operations = redisTemplate.opsForValue();
        TokenInfo tokenInfo = new TokenInfo();
        tokenInfo.setTokenType(tokenType);
        tokenInfo.setAppInfo(appInfo);
        operations.set(token, tokenInfo, 7200, TimeUnit.SECONDS);
        AccessToken accessToken = new AccessToken(token, expireTime);
        return accessToken;
    }

    public static void main(String[] args) {
        long timestamp = System.currentTimeMillis();
        System.out.println(timestamp);
        //signString = timestamp+app_id+app_secret
        String signString = timestamp + "111111" + "222222";
        String sign = MD5Util.encode(signString);
        System.out.println(sign);

        System.out.println("-------------------");
        signString = "password=123456&username=1&12345678954556" + "ff03e64b-427b-45a7-b78b-47d9e8597d3b1529815393153sdfsdfsfs" + timestamp + "A1scr6";
        sign = MD5Util.encode(signString);
        System.out.println(sign);
    }


}
